

import inspect
import sys,os,json,time
p=os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))))
p=os.path.dirname(os.path.dirname(os.path.dirname(os.path.dirname(p))))
p=p+os.sep+'_base_tool'+os.sep+'python'
sys.path.append(p)
from base_class1_0 import base_class # type: ignore
import paho.mqtt.client as mqtt


#快速查找 注册了100w条path,匹配一条path的时间在0s左右
class a_1_0_0_0_0_fast_find:
    def __init__(self,bind_func=None):
        self.bind_func=bind_func
        self.fast_dict={}#快速搜索字典
    #添加路径
    def add(self,**kwargs):
        """
        path:路径 如/eee/eer/#
        info:{"path":path,"handle":func} func是执行的回调函数
        """
        path=kwargs.get("path")
        if self.bind_func is not None:
            self.bind_func(path,qos=1)
        new_dct=self.fast_dict
        for i in path:
            new_dct2=new_dct.get(i)
            if new_dct2 is None:
                new_dct[i]={}
                new_dct=new_dct[i]
            else:
                new_dct=new_dct2
        new_dct['value']=kwargs 
        # print("绑定path:",path)
    #TODO:删除绑定
    def dele(self,**kwargs):
        pass
    #查找路径
    def find(self,path):
        match_path=''
        now_dict=self.fast_dict
        for i in path:
            # print('find',i,topics)
            if '#'in now_dict:
                return {"match_path":match_path+'#',"info":now_dict['#']['value']}
            else:
                match_path+=i
                now_dict=now_dict.get(i)
                if now_dict is None:return#没有匹配到
        if now_dict.get('value'):return {"match_path":match_path,"info":now_dict['value']}
        elif now_dict.get('#')is not None:return {"match_path":match_path+'#',"info":now_dict['#']['value']}
        else:return None#没有匹配到
    def handle(self,path,data):
        now_info=self.find(path)#查找topic
        #如果对topic进行处理
        if now_info is not None:
            # print("匹配到path:",path)
            # print("\t\t数据:",data)   
            #执行对应topic的handle函数
            now_info['info']['handle'](data=data,path=path)

class a_1_0_0_0_0(base_class):
    #匹配topic
    def on_message(self, client, userdata, msg):  
        topic = msg.topic  
        payload = msg.payload.decode()
        #快速查找到匹配路径 然后执行回调函数
        self.a_1_0_0_0_0_fast_find_obj.handle(topic,payload)  
        
    def run_server(self,callback_lst=list()):
        test=True
        self.host=self.process_input.get("host")
        self.port=self.process_input.get("port")
        self.username=self.process_input.get("username")
        self.passwd=self.process_input.get("passwd")
        self.client_name=self.process_input.get("client_name")
        
        self.client = mqtt.Client(client_id=self.client_name)#初始化客户端
        self.client.username_pw_set(self.username, self.passwd)#设置账号密码
        self.client.on_message = self.on_message#设置回调函数
        self.client.on_connect = self.on_connect# 设置连接成功回调函数
        self.a_1_0_0_0_0_fast_find_obj=a_1_0_0_0_0_fast_find(self.client.subscribe)#创建topic快速匹配对象
        self.client.connect(self.host, self.port, keepalive=60)# 连接MQTT服务器，keepalive为60秒
        if test:print("mqtt的host和port:",self.host, self.port)
        for item in callback_lst:
            self.sub(**item)
        self._recv_thread()#与其他进程进行通信的socket服务（用于接收数据
        self.client.loop_forever()  # 这将启动一个阻塞循环，处理网络流量、重连等
    def on_connect(self, client, userdata, flags, rc):
        """
        连接成功回调函数，会在 MQTT 客户端连接成功时被调用

        :param client: MQTT 客户端实例
        :param userdata: 用户数据
        :param flags: 标志位
        :param rc: 返回码

        - 返回码说明:
            * 0:连接成功
            * 1:协议版本不正确
            * 2:客户端标识符无效
            * 3:服务器不可用
            * 4:用户名或密码不正确
            * 5:未经授权
        """
        rc_status = [
            "连接成功", "协议版本不正确", "客户端标识符无效", "服务器不可用", "用户名或密码不正确", "未经授权"]
        print("connect:", rc_status[rc], rc)

    # 定义消息到达的回调函数
    def on_message(self,client, userdata, msg):
        res=self.a_1_0_0_0_0_fast_find_obj.find(msg.topic)
        try:
            print("start run callback",msg.topic)
            self.a_1_0_0_0_0_fast_find_obj.find(msg.topic)["info"]["callback"](
                **{
                    "client":client,
                    "topic":msg.topic,
                    "data":json.loads(msg.payload.decode())
                }
            )
            print("start run callback 2")
        except:
            print("error:未匹配到topic:",msg.topic)
    def sub(self,**kwargs):
        # topic='/topic/test1',callback=lambda client,topic,msg:print(f"topic:{topic}\nmsg:{msg}")
        self.a_1_0_0_0_0_fast_find_obj.add(**{
            "path":kwargs.get("topic"),
            "callback":kwargs.get("callback")
        })
if __name__=="__main__":
    import time
    t1=time.time()
    t2=None
    a=1

    def f(c,t,m):
        global a,t1,t2
        a+=1
        if(a%1000==0):
            t2=time.time()
            print(a,":",t2-t1)
            t1=t2
    init_lst=[
        {'path':"/topic/test2",
         "callback":f
         }
    ]
    a_1_0_0_0_0_obj=a_1_0_0_0_0(**{
        "flow_chat_use_compontent":{"1":{"process_id":"1","name":"d","flow_dir":[-1]}},
        "name":"dd",
        "process_id":"1",
        "temp_id":"1",
        "project_path":[1,2,3,4,5],
        "all_obj":{},

'recv_port':5775,"recv_ip":"127.0.0.1",
"host":"39.106.34.123","port":1883,"username":"","passwd":"","client_name":"test",
    }).run_server(init_lst)
        
